import { _decorator, Component, Node, Vec3 } from 'cc';
import { Grid } from './Grid/Grid';
import { AStarNode } from './AstarNode';
const { ccclass, property } = _decorator;

@ccclass('AstarPathfinder')
export class AStarPathfinder {
    private grid: Grid;
    
    constructor(grid: Grid) {
        this.grid = grid;
    }
    
    public findPath(startPos: Vec3, endPos: Vec3): Vec3[] {
        // 转换坐标
        const startGrid = this.grid.worldToGrid(startPos);
        const endGrid = this.grid.worldToGrid(endPos);
        
        // 检查起点和终点是否可通行
        // if (!this.grid.isWalkable(startGrid.x, startGrid.y)) return [];
        // if (!this.grid.isWalkable(endGrid.x, endGrid.y)) return [];
        
        // 初始化开放列表和关闭列表
        const openList: AStarNode[] = [];
        const closedList: AStarNode[] = [];
        
        // 添加起点到开放列表
        const startNode = new AStarNode(startGrid.x, startGrid.y);
        openList.push(startNode);
        
        // 8方向移动的偏移量
        const directions = [
            {x: 0, y: -1},  // 上
            {x: 1, y: 0},   // 右
            {x: 0, y: 1},   // 下
            {x: -1, y: 0},  // 左
            {x: 1, y: -1}, // 右上
            {x: 1, y: 1},  // 右下
            {x: -1, y: 1},  // 左下
            {x: -1, y: -1} // 左上
        ];
        
        while (openList.length > 0) {
            // 获取F值最小的节点
            let currentNode = openList[0];
            let currentIndex = 0;
            
            for (let i = 1; i < openList.length; i++) {
                if (openList[i].f < currentNode.f) {
                    currentNode = openList[i];
                    currentIndex = i;
                }
            }
            
            // 当前节点移动到关闭列表
            openList.splice(currentIndex, 1);
            closedList.push(currentNode);
            
            // 找到目标
            if (currentNode.x === endGrid.x && currentNode.y === endGrid.y) {
                return this.retracePath(startNode, currentNode);
            }
            
            // 检查相邻节点
            for (const dir of directions) {
                const neighborX = currentNode.x + dir.x;
                const neighborY = currentNode.y + dir.y;
                
                // 检查是否可通行且不在关闭列表中
                if (!this.grid.isWalkable(neighborX, neighborY) || 
                    this.isInList(closedList, neighborX, neighborY)) {
                    continue;
                }
                
                // 对角线移动成本更高
                const moveCost = (dir.x !== 0 && dir.y !== 0) ? 1.414 : 1;
                const newGCost = currentNode.g + moveCost;
                
                let neighborNode = this.isInList(openList, neighborX, neighborY);
                
                if (!neighborNode || newGCost < neighborNode.g) {
                    if (!neighborNode) {
                        neighborNode = new AStarNode(neighborX, neighborY);
                        openList.push(neighborNode);
                    }
                    
                    neighborNode.g = newGCost;
                    neighborNode.h = this.heuristic(neighborX, neighborY, endGrid.x, endGrid.y);
                    neighborNode.f = neighborNode.g + neighborNode.h;
                    neighborNode.parent = currentNode;
                }
            }
        }
        
        return []; // 没有找到路径
    }
    
    private heuristic(x1: number, y1: number, x2: number, y2: number): number {
        // 使用曼哈顿距离
        return Math.abs(x1 - x2) + Math.abs(y1 - y2);
    }
    
    private isInList(list: AStarNode[], x: number, y: number): AStarNode | null {
        for (const node of list) {
            if (node.x === x && node.y === y) {
                return node;
            }
        }
        return null;
    }
    
    private retracePath(startNode: AStarNode, endNode: AStarNode): Vec3[] {
        const path: Vec3[] = [];
        let currentNode = endNode;
        
        while (currentNode !== startNode) {
            path.push(this.grid.gridToWorld(currentNode.x, currentNode.y));
            currentNode = currentNode.parent!;
        }
        
        path.reverse(); // 反转路径，从起点到终点
        return path;
    }
}

